#include <Windows.h>
#include <stdio.h>

// 声明需要的信号量
HANDLE MyMutex = NULL;
HANDLE myEmpty = NULL, myFull = NULL;


const int n = 30; //缓冲区大小
const int threads_num = 2; //进程个数
HANDLE Threads[threads_num];

//需要使用的全局变量
int in = 0, out = 0;
int item[n];

// 生产者线程
void WINAPI Producer(void *param)
{
    printf("生产者线程 %u 开始运行\n", GetCurrentThreadId());
    int itemproduce = 0;
    while(true){
        Sleep(200); //生产时间
        WaitForSingleObject(myEmpty, INFINITE);
        WaitForSingleObject(MyMutex, INFINITE);
        item[in] = itemproduce;
        printf("生产: %d \n",item[in]);
        itemproduce++; //区分生产者生产的内容
        in = (in + 1)%n;
        ReleaseMutex(MyMutex);
        ReleaseSemaphore(myFull, 1, NULL);
    }
}

// 消费者线程
void WINAPI Consumer(void *param)
{
    printf("消费者线程 %u 开始运行\n", GetCurrentThreadId());
    while(true){
        WaitForSingleObject(myFull, INFINITE);
        WaitForSingleObject(MyMutex, INFINITE);
        printf("取出: %d \n",item[out]);
        out = (out+1)%n;
        ReleaseMutex(MyMutex);
        ReleaseSemaphore(myEmpty, 1, NULL);
        Sleep(100); //消费时间
    }
}

// 创建线程
void creatThreads()
{
    DWORD dwThreadID = 0;
    if ((Threads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL, 0, &dwThreadID)) == NULL)
    {
        printf("生产者线程创建失败！\n");
        exit(0);
    }
    else
    {
        printf("生产者线程 %u 创建成功\n", dwThreadID);
    }

    if ((Threads[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &dwThreadID)) == NULL)
    {
        printf("消费者线程创建失败！\n");
        exit(0);
    }
    else
    {
        printf("消费者线程 %u 创建成功\n", dwThreadID);
    }
}

int main()
{
    // 生产者消费者问题-初始化信号量
    printf("赵胜达的生产者消费者问题解决方案：\n");
    HANDLE MyMutex = CreateMutex(NULL, FALSE, "mutex-ZSD");
    myEmpty = CreateSemaphore(NULL, n, n, "Empty");
    myFull = CreateSemaphore(NULL, 0, n, "Full");
    // 调用创建进程函数初始化读者和写着进程
    creatThreads();
    //确保线程间的相互等待
    WaitForMultipleObjects(threads_num, Threads, TRUE, INFINITE);
    return 0;
}